home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung CD 2 (Tewi)(1994).iso / doc / mir / f_print.c < prev    next >
Text File  |  1992-07-02  |  13KB  |  383 lines

  1. /*
  2.  *  usage:  f_print file_name [/a][/w] [ from_byte  to_byte ] > subset
  3.  *
  4.  *  F_PRINT Reduces a file to printable characters only.  If the /w
  5.  *          option is specified, strings of printable characters that
  6.  *          are unlikely to be words are filtered out as well, and
  7.  *          each new burst of accepted text is placed on a new line.
  8.  *          /a causes accented characters to be accepted as printable.
  9.  *
  10.  *  input:  Any file whatsoever, or any part of a file.
  11.  *
  12.  *  output: Printable subset.
  13.  *
  14.  *  writeup: MIR TUTORIAL ONE, topic 5
  15.  *
  16.  *  Written:    Douglas Lowry   Jan 07 92
  17.  *  Modified:   Douglas Lowry   Feb 27 92
  18.  *              Copyright (C) 1992 Marpex Inc.
  19.  *
  20.  *    The MIR (Mass Indexing and Retrieval) Tutorials explain detailed
  21.  *    usage and co-ordination of the MIR family of programs to analyze,
  22.  *    prepare and index databases (small through gigabyte size), and
  23.  *    how to build integrated retrieval software around the MIR search
  24.  *    engine.  The fifth of the five MIR tutorial series explains how
  25.  *    to extend indexing capability into leading edge search-related
  26.  *    technologies.  For more information, GO IBMPRO on CompuServe;
  27.  *    MIR files are in the DBMS library.  The same files are on the
  28.  *    Canada Remote Systems BBS.  A diskette copy of the Introduction
  29.  *    is available by mail ($10 US... check, Visa or Mastercard);
  30.  *    diskettes with Introduction, Tutorial ONE software and the
  31.  *    shareware Tutorial ONE text cost $29.  Shareware registration
  32.  *    for a tutorial is also $29.
  33.  *
  34.  *    E-mail...
  35.  *                Compuserve  71431,1337
  36.  *                Internet    doug.lowry%canrem.com
  37.  *                UUCP        canrem!doug.lowry
  38.  *                Others:     doug.lowry@canrem.uucp
  39.  *
  40.  *    FAX...                  416 963-5677
  41.  *
  42.  *    "Snail mail"...         Douglas Lowry, Ph.D.
  43.  *                            Marpex Inc.
  44.  *                            5334 Yonge Street, #1102
  45.  *                            North York, Ontario
  46.  *                            Canada  M2N 6M2
  47.  *
  48.  *    Related database consultation and preparation services are
  49.  *    available through:
  50.  *              Innotech Inc., 2001 Sheppard Avenue E., Suite #118,
  51.  *              North York, Ontario  Canada   M2J 4Z7
  52.  *              Tel.  416 492-3838   FAX  416 492-3843
  53.  *
  54.  *  This program is free software; you may redistribute it and/or
  55.  *  modify it under the terms of the GNU General Public License as
  56.  *  published by the Free Software Foundation; either version 2 of
  57.  *  the License, or (at your option) any later version.
  58.  *
  59.  *  This program is distributed in the hope that it will be useful,
  60.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  61.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  62.  *  GNU General Public License for more details.
  63.  *
  64.  *  You should have received a copy of the GNU General Public License
  65.  *  (file 05LICENS) along with this program; if not, write to the
  66.  *  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
  67.  *  USA.
  68.  */
  69.  
  70. #include <stdio.h>
  71. #include <stdlib.h>
  72. #include <ctype.h>
  73.  
  74. #define     BIGBUF      2048
  75. #define     STORE       32
  76.  
  77. #define     NON_PRINT       0
  78. #define     WHITE_SPACE     1
  79. #define     PUNCTUATION     2
  80. #define     DIGIT           3
  81. #define     CONSONANT       4
  82. #define     VOWEL           5
  83. #define     HI_CONSONANT    6
  84. #define     HI_VOWEL        7
  85. #define     TYPE_CT         8       /*  count of above types    */
  86.  
  87. #define     repeat      for(;;)
  88.  
  89. /*
  90.  * declarations 
  91.  */
  92.  
  93. typedef     enum        _bool
  94.              { FALSE = 0, TRUE = 1 }  Bool;
  95.  
  96.     void        Usage_(), process(), clear_store() ;
  97.     Bool        check_store() ;
  98.     char        *Cmdname_() {    return( "f_print" );  }
  99.  
  100. /*
  101.  *  GLOBAL VARIABLES
  102.  */
  103.  
  104.     static unsigned char   table[256] = {
  105.          0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, /* ctls */
  106.          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ctls */
  107. /*      bl  !  "  #  $  %  &  '  (  )  *  +  ,  -  .  /     */
  108.          1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2,
  109. /*       0  1  2  3  4  5  6  7  8  9  :  ;  <  =  >  ?     */
  110.          3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2,
  111. /*       @  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O     */
  112.          4, 5, 4, 4, 4, 5, 4, 4, 4, 5, 4, 4, 4, 4, 4, 5,
  113. /*       P  Q  R  S  T  U  V  W  X  Y  Z  [  \  ]  ^  _     */
  114.          4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 2, 2, 2, 2, 2,
  115. /*       `  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o     */
  116.          2, 5, 4, 4, 4, 5, 4, 4, 4, 5, 4, 4, 4, 4, 4, 5,
  117. /*       p  q  r  s  t  u  v  w  x  y  z  {  |  }  ~  NULL  */
  118.          4, 4, 4, 4, 4, 5, 4, 4, 4, 5, 4, 2, 2, 2, 2, 0,
  119. /*       Ç  ü  é  â  ä  à  å  ç  ê  ë  è  ï  î  ì  Ä  Å     */
  120.          6, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7,
  121. /*       É  æ  Æ  ô  ö  ò  û  ù  ÿ  Ö  Ü  ¢  £  ¥  ₧  ƒ     */
  122.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0,
  123. /*       á  í  ó  ú  ñ  Ñ  ª  º  ¿  ⌐  ¬  ½  ¼  ¡  «  »     */
  124.          7, 7, 7, 7, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  125.          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  126.          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  127.          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  128.          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  129.          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  130.             };
  131.  
  132. /*
  133.  * MAIN
  134.  */
  135.  
  136. main( argc, argv )
  137.     int  argc;
  138.     char **argv;
  139. {
  140.     FILE    *fp ;
  141.     char    c10 ;
  142.     Bool    words,
  143.             accent_ok,          /*  allow accented chars          */
  144.             got_from ;          /*  found a "from_byte" argument  */
  145.     int     i ;
  146.     long    fr_byte, to_byte;   /*  byte range      */
  147.  
  148.     /*  usage:  f_print file_name [/a][/w] [ from_byte  to_byte ] */
  149.  
  150.     c10 = argv[1][0] ;
  151.     if( argc < 2 || argc > 6 || c10 == '-' || c10 == '/' || c10 == '?' )
  152.         Usage_() ;
  153.  
  154.     if(( fp = fopen( argv[1], "rb" )) == NULL )
  155.     {
  156.         fprintf( stderr, "\nUnable to open file %s.\n", argv[1] );
  157.         Usage_();
  158.     }
  159.  
  160.     words = got_from = accent_ok = FALSE ;
  161.     fr_byte = 0 ;
  162.     to_byte = 0x0fffffff ;
  163.  
  164.     for( i = 2 ; i < argc ; i++ )
  165.     {
  166.         if( islower( argv[i][1] ))
  167.             argv[i][1] = toupper( argv[i][1] ) ;
  168.         c10 = argv[i][0] ;
  169.         if(( c10 == '-' || c10 == '/' ) && argv[i][1] == 'W' )
  170.             words = TRUE ;
  171.         else if(( c10 == '-' || c10 == '/' ) && argv[i][1] == 'A' )
  172.             accent_ok = TRUE ;
  173.         else if( got_from )
  174.             to_byte = atol( argv[i] ) ;
  175.         else
  176.         {
  177.             fr_byte = atol( argv[i] );
  178.             got_from = TRUE ;
  179.         }
  180.     }
  181.  
  182.     if( fr_byte )
  183.     {
  184.         if( fseek( fp, fr_byte, SEEK_SET ))
  185.         {
  186.             fprintf( stderr, "Unable to position %s to %ld\n",
  187.                 argv[1], fr_byte );
  188.             Usage_() ;
  189.         }
  190.     }
  191.  
  192.     process( fp, fr_byte, to_byte, accent_ok, words ) ;
  193.  
  194.     fclose( fp );
  195.     exit( 0 );
  196. }
  197. /*
  198.  *  Usage
  199.  */
  200.     void
  201. Usage_()
  202. {
  203.     fprintf( stderr,
  204. "\nUsage: %s file_name [/a][/w] [ from_byte  to_byte ] > subset\n\n\
  205.         Reduces a file to printable characters only.  If the /w\n\
  206.         option is specified, strings of printable characters that\n\
  207.         are unlikely to be words are filtered out as well, and\n",
  208.             Cmdname_() ) ;
  209.     fprintf( stderr,
  210. "        each new burst of accepted text is placed on a new line.\n\
  211.         /a causes accented characters to be accepted as printable.\n\n\
  212. input:  Any file whatsoever, or any part of a file.\n\n\
  213. output: Printable subset.\n\n\
  214. writeup: MIR TUTORIAL ONE, topic 5\n\n" ) ;
  215.     exit( 1 ) ;
  216. }
  217. /*
  218.  *  PROCESS -   Passes through file from starting position,
  219.  *              filtering out unprintable material.
  220.  */
  221.     void
  222. process( fp, fr_byte, to_byte, accent_ok, words )
  223.     FILE        *fp ;
  224.     long int    fr_byte,    /*  beginning offset        */
  225.                 to_byte ;   /*  ending offset           */
  226.     Bool        accent_ok,
  227.                 words ;
  228. {
  229. /*  The technique implemented below tests only the first STORE
  230.  *  characters of a printable sequence.  Once this limit is reached,
  231.  *  we assume full printability until a NON_PRINT character is found.
  232.  *  The function check_store controls the criteria for whether the
  233.  *  start of a printable sequence passes.
  234.  */
  235.     unsigned char   buffer[ BIGBUF ],
  236.                     store[ STORE ],
  237.                     uc ;
  238.     long int        offset,     /*  cumulative bytes into file   */
  239.                     up_to ;     /*  test one beyond "to_byte"    */
  240.     int             buflen,     /*  of buffer contents           */
  241.                     in_store,   /*  consecutive bytes in store   */
  242.                     stor_typ[TYPE_CT],  /*  count each type in store */
  243.                     type,       /*  of character per table above */
  244.                     prev_type,  /*  previous type                */
  245.                     i, j, pt ;
  246.  
  247.     offset = fr_byte ;
  248.     up_to = to_byte + 1 ;
  249.     prev_type = type = NON_PRINT ;
  250.     clear_store( &in_store, stor_typ ) ;
  251.  
  252.     repeat
  253.     {
  254.         if( offset++ > up_to )
  255.             break ;
  256.         buflen = fread( buffer, sizeof( char ), BIGBUF, fp );
  257.         if( !buflen )
  258.             break ;
  259.  
  260.         for( pt = 0 ; pt < buflen ; pt ++ )
  261.         {
  262.             offset++ ;
  263.             if( offset > up_to )
  264.                 break ;
  265.             uc = buffer[ pt ] ;
  266.             prev_type = type ;
  267.             type = table[ uc ] ;
  268.  
  269.             if( !accent_ok && ( type == HI_CONSONANT || type == HI_VOWEL ))
  270.                 type = NON_PRINT ;
  271.  
  272.             /*  Two accented characters in sequence are not printable */
  273.  
  274.             if(( prev_type == HI_CONSONANT || prev_type == HI_VOWEL )
  275.                 && (  type == HI_CONSONANT || type == HI_VOWEL ))
  276.             {
  277.                 type = NON_PRINT ;
  278.                 in_store-- ;
  279.             }
  280.  
  281.             if( type == NON_PRINT )
  282.             {
  283.                 if( words && in_store == STORE )
  284.                     putchar( '\n' );
  285.                 else if( words && in_store &&
  286.                      check_store( in_store, stor_typ ))
  287.                 {
  288.                     for( i = 0 ; i < in_store ; i++ )
  289.                     {
  290.                         if( putchar( store[i] ) != store[i] )
  291.                         {
  292.                             fprintf( stderr,
  293.                                 "Unable to write... FATAL.\n\n" );
  294.                             exit( 1 );
  295.                         }
  296.                     }
  297.                     putchar( '\n' );
  298.                 }
  299.                 if( in_store )
  300.                     clear_store( &in_store, stor_typ ) ;
  301.                 continue ;
  302.             }
  303.  
  304.             /*  printable characters - output or add to store   */
  305.  
  306.             if( !words || in_store == STORE )
  307.             {
  308.                 if( putchar( uc ) != uc )
  309.                 {
  310.                     fprintf( stderr, "Unable to write... FATAL.\n\n" );
  311.                     exit( 1 );
  312.                 }
  313.             }
  314.             else
  315.             {
  316.                 store[ in_store++ ] = uc ;
  317.                 stor_typ[ type ]++ ;
  318.                 if( in_store == STORE )
  319.                 {
  320.                     if( !check_store( in_store, stor_typ ))
  321.                         clear_store( &in_store, stor_typ ) ;
  322.                     else
  323.                     {
  324.                         for( i = 0 ; i < in_store ; i++ )
  325.                         {
  326.                             if( putchar( store[i] ) != store[i] )
  327.                             {
  328.                                 fprintf( stderr,
  329.                                     "Unable to write... FATAL.\n\n" );
  330.                                 exit( 1 );
  331.                             }
  332.                         }
  333.                     }
  334.                 }
  335.             }
  336.         }
  337.     }
  338.     return;
  339. }
  340. /*
  341.  *  CLEAR_STORE
  342.  */
  343.     void
  344. clear_store( in_store, stor_typ )
  345.     int     *in_store,    /*  consecutive bytes in store */
  346.             stor_typ[ TYPE_CT ];  /*  count each type in store   */
  347. {
  348.     int     i ;
  349.  
  350.     *in_store = 0 ;
  351.     for( i = 1 ; i < TYPE_CT ; i++ )
  352.         stor_typ[ i ] = 0 ;
  353.     return ;
  354. }
  355. /*
  356.  *  CHECK_STORE - Is the series held in "store" valid "words"?
  357.  *
  358.  *  In the version that follows, a series passes if it contains 5 or
  359.  *  more bytes made up of:
  360.  *      1.  digits with NO vowels AND NO consonants
  361.  *      2.  vowels AND consonants (with or without digits)
  362.  *
  363.  *  You may wish to try alternative forms of this function.  Its objective
  364.  *  is to maximize retention of desired text while minimizing retention of
  365.  *  junk.  Proximity might be considered... more than 4 consonants in a
  366.  *  row, no vowels between white spaces, etc.
  367.  */
  368.     Bool
  369. check_store( in_store, typ )
  370.     int     in_store,
  371.             typ[ TYPE_CT ]; /*  count each type in store      */
  372. {
  373.     if( in_store < 5 )
  374.         return( FALSE );
  375.     typ[ CONSONANT ] += typ[ HI_CONSONANT ] ;
  376.     typ[ VOWEL ] += typ[ HI_VOWEL ];
  377.     if( typ[ DIGIT ] && !typ[ CONSONANT ] && !typ[ VOWEL ] )
  378.         return( TRUE ) ;
  379.     if( typ[ CONSONANT ] && typ[ VOWEL ] )
  380.         return( TRUE ) ;
  381.     return( FALSE ) ;
  382. }
  383.